using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Xml.Serialization;

namespace Kopain
{

    /// <summary>This is the main editing form containing a tree view and an editor.
    /// </summary>
    public partial class frmMain : FormBase
    {

#region Private properties.

        //private string _fileNameAndPath;


        private Savefile _saveFile;
	 
#endregion  //MyPrivate properties.

#region Public properties.


#endregion  //Public properties.

#region Constructor.

        public frmMain()
        {
            InitializeComponent();
        }


        //public frmMain( )
        //{
        //    //_fileNameAndPath = fileNameAndPath;
        //    InitializeComponent();
        //}

#endregion  //Constructor.

#region Event sinks.

#region Form events.

        private void frmMain_Load( object sender, EventArgs e )
        {
            //TODO:Make a check here if there were any parameters to the exe.  A parameter is a filename and it should be opened.
            Setup( null );
        }

        private void frmMain_FormClosing( object sender, FormClosingEventArgs e )
        {
            ClosingFormCheck();
        }

        private void frmMain_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (e.KeyChar == (char)Keys.Escape)
            {
                switch (KopainSetting.Instance.Settings.KeyAction.Esc)
                {
                    case KeyActionTypesEsc.Close:
                        CloseApplication();
                        break;
                    case KeyActionTypesEsc.Minimize:
                        HideApplication();
                        break;
                    default:
                        throw new ApplicationException("tba");
                }
            }
        }

#endregion  //Form events.

#region Control events.

#region Tree view events.

        /// <summary>This method is fired before the node/note is changed.
        /// </summary>
        /// <param name="previousNode">The node before changing.</param>
        /// <param name="eventArgsNextNode">A framework enum containing amongst other the next node.
        /// It also contains a cancel parameter.</param>
        private void tvNotes_OnBeforeBeforeSelect(TreeNode previousNode, TreeViewCancelEventArgs eventArgsNextNode)
        {
            System.Diagnostics.Debug.WriteLine("FormMain.tvNotes_OnBeforeBeforeSelect", "Enter"); System.Diagnostics.Debug.Indent();

            if (null != previousNode)
            {
                //  Only save if the file exists.
                if (txtNote.Enabled)
                {
                    NoteType previousNote = NotesTreeview.GetNote(previousNode);
                    SaveNote(previousNote);
                }
            }

            System.Diagnostics.Debug.Unindent(); System.Diagnostics.Debug.WriteLine("FormMain.tvNotes_OnBeforeBeforeSelect", "Leave");
        }

        private void tvNotes_BeforeSelect(object sender, TreeViewCancelEventArgs e)
        {

        }

        private void tvNotes_AfterSelect(object sender, TreeViewEventArgs e)
        {
            //  After selection of a new node; the editor must be updated.
            //  Either the text is taken from a file or directly from the File.
            NoteType activeNote = NotesTreeview.GetNote(e.Node);
            string fileName = activeNote.file;
            txtNote.Enabled = true;

            if (string.Empty == fileName)
            {   // There is no filename so the data is stored right in the Savefile.
                txtNote.Rtf = activeNote.Data;
            }
            else
            {   // The text is stored in an external file.
                try
                {
                    txtNote.Rtf = GetContentsOfFile(activeNote.FileWithPath(_saveFile.NoteRoot));
                }
                catch (Exception.FileWasNotFoundException exc)
                {
                    txtNote.Text = string.Format("The file [{0}] was not found.", exc.Filename);
                    txtNote.Enabled = false;
                }
            }

            // If the text happens to get shorter than the cursorPosition, like it is an external file that is updated by another program - we position it last.  Normally by cursorPosition though.
            txtNote.SelectionStart = Math.Min(txtNote.Text.Length, activeNote.cursorPosition); 
            
            UpdateStatuslist(activeNote);
        }

        /// <summary>This method is fired after the label of the node is changed.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void tvNotes_AfterLabelEdit(object sender, NodeLabelEditEventArgs e)
        {
            //  Quit editing the label.
            e.Node.EndEdit(false);

            //  If the user cancelled the name change ( pressed Esc ) we get a null in the Label.
            //  Then it shouldn't be stored.
            if (null != e.Label)
            {
                NotesTreeview.GetNote(e.Node).title = e.Label;
            }
            SaveSavefile();
        }

#endregion  //  Tree view events.

#region Editor events.

        /// <summary>This event is raised when the user wants to move between notes.
        /// </summary>
        /// <param name="navigateType"></param>
        private void txtNote_OnNavigate(NotesTextbox.NavigateTypes navigateType)
        {
            System.Diagnostics.Debug.WriteLine("FormMain.txtNote_OnNavigate", "Enter"); System.Diagnostics.Debug.Indent();

            SelectRelativeNode(navigateType);

            System.Diagnostics.Debug.Unindent(); System.Diagnostics.Debug.WriteLine("FormMain.txtNote_OnNavigate", "Leave");
        }

        /// <summary>When the user wants to move to the next panel from the editor it is the treeview.  Until the layout is changed and it is something else.
        /// </summary>
        private void txtNote_OnSetFocusToNextPanel()
        {
            tvNotes.Focus();
        }

        /// <summary>When the user wants to move to the next panel from the editor it is the treeview.  Until the layout is changed and it is something else.
        /// </summary>
        private void txtNote_OnSetFocusToPreviousPanel()
        {
            tvNotes.Focus();
        }

#endregion  //  Editor events.`

#endregion  //Control events.

#region Menu event sinks.

#region File menu.

        private void mnuSavefileNew_Click( object sender, EventArgs e )
        {
            CreateNewFile();
        }

        private void mnuSavefileOpen_Click( object sender, EventArgs e )
        {
            OpenExistingFile();
        }

        private void mnuSavefileSave_Click(object sender, EventArgs e)
        {
            this.SaveSavefile();
        }
        
        private void mnuRecentFiles_DropDownOpening( object sender, EventArgs e )
        {
            PopulateMRUList();
        }

        /// <summary>This event handler is called whenever the user chooses one of the recent files from the MRU list.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void mnuMRUItem_Click( object sender, EventArgs e )
        {
            ToolStripMenuItem mnu = (ToolStripMenuItem)sender;
            SaveNote( tvNotes.GetSelectedNote() );
            SaveSavefile();
            LoadAndShowSavefile( mnu.Text );
        }

        private void mnuSavefileExport_Click( object sender, EventArgs e )
        {
            ExportSavefile();
        }

        private void mnuApplicationExit_Click( object sender, EventArgs e )
        {
            CloseApplication();
        }

#endregion  //  File menu.

#region Tree menu.
        
        private void mnuTreeNodeAddSibling_Click( object sender, EventArgs e )
        {
            TreeNodeAddSibling();
        }

        private void mnuTreeNodeAddChild_Click( object sender, EventArgs e )
        {
            TreeNodeAddChild();
        }

        private void mnuTreeNodeChangeName_Click(object sender, EventArgs e)
        {
            TreeNodeChangeName();
        }

        private void mnuTreeNodeDelete_Click(object sender, EventArgs e)
        {
            if( DialogResult.Yes == MessageBox.Show( this,
                "Do you want to delete the current note?\r\nThis action cannot be undone.", "Kopain - Delete Note",
                MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button1 ) )
            {
                TreeNodeDelete();
            }
        }

        private void mnuTreeNodeMoveDown_Click( object sender, EventArgs e )
        {
            TreeNodeMoveDown();
        }

        private void mnuTreeNodeMoveLeft_Click( object sender, EventArgs e )
        {
            TreeNodeMoveLeft();
        }

        private void mnuTreeNodeMoveRight_Click( object sender, EventArgs e )
        {
            TreeNodeMoveRight();
        }

        private void mnuTreeNodeMoveUp_Click(object sender, EventArgs e)
        {
            TreeNodeMoveUp();
        }

#endregion  //  Tree menu.

#region Note menu.

        private void mnuNoteInfoShow_Click(object sender, EventArgs e)
        {
            ShowNoteInfo();
        }

        private void mnuNoteLinkToFile_Click(object sender, EventArgs e)
        {
            if ("" != txtNote.Rtf.Trim())
            {
                if (DialogResult.Yes == MessageBox.Show(this,
                    "The text will be lost, are you sure you want to link to a new file?", "Kopain - Link Note",
                    MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2))
                {
                    using (OpenFileDialog dlg = new OpenFileDialog())
                    {
                        NoteType activeNote = tvNotes.GetSelectedNote();
                        dlg.InitialDirectory = activeNote.Root.path;
                        if (DialogResult.OK == dlg.ShowDialog(this))
                        {
                            string linkFile = dlg.FileName;
                            if (Path.GetDirectoryName(linkFile) + @"\" == activeNote.Root.path)
                            {
                                activeNote.file = Path.GetFileName(linkFile);
                            }
                            else
                            {
                                activeNote.file = linkFile;
                            }
                            txtNote.Rtf = File.ReadAllText(linkFile);
                            activeNote.Data = "";
                            SaveSavefile();
                            UpdateStatuslist(activeNote);
                        }
                    }
                }
            }
        }

#endregion  //  Note menu.

#endregion  //Menu event sinks.

#endregion  //Event sinks.

#region Presentation methods.

#region Application methods.

        /// <summary>This method closes the application.
        /// This is not totally true since it just closes the form and not the application.  Well?
        /// </summary>
        private void CloseApplication()
        {
            Application.Exit();
        }

#endregion  //  Application methods.

#region Form methods.

        /// <summary>This method checks if it is ok to close the form and does the tidying up, like saving.
        /// </summary>
        private void ClosingFormCheck()
        {
            // Store which Note was last open so we can open it again next time the form is opened.
            string idOfSelectedNote = tvNotes.GetSelectedNote().id;
            _saveFile.NoteRoot.openNoteId = idOfSelectedNote;


            //  Set the visible flag for all nodes.
            //
            foreach (LIUS.Templates.Tuple.Tuple<bool, NoteType> tupleVisible in tvNotes.GetVisibleStatusOfNodes())
            {
                tupleVisible.Last.visible = tupleVisible.First;
            }

            //  Save the file if there is any.
            //
            if (null != _saveFile)
            {
                //  Only save the note is something is selected.  The moment the user selects the textbox a node is selected
                //  so if no node is selected we can be quite sure no change is made to the note.
                if (null != tvNotes.SelectedNode)
                {
                    SaveNote(NotesTreeview.GetNote(tvNotes.SelectedNode));
                }
            }
        }

        /// <summary>This method hides the application.
        /// </summary>
        private void HideApplication()
        {
            this.WindowState = FormWindowState.Minimized;
        }

        /// <summary>This method does some basic setup.
        /// </summary>
        private void Setup(string filename)
        {

            //  We have to get an event _before_  the UI changes the node/note.  Therefore we have to connect to an
            //  event that fires before the new node/note is shown.
            this.tvNotes.OnBeforeBeforeSelect += new NotesTreeview.BeforeBeforeSelectDelegate(tvNotes_OnBeforeBeforeSelect);

            //  The user can change Note from within the textbox.  Then this event is fired.
            this.txtNote.OnNavigate += new NotesTextbox.NavigateDelegate(txtNote_OnNavigate);

            //  The user can move out of the editor through a keypress.
            this.txtNote.OnSetFocusToNextPanel += new NotesTextbox.SetFocusToOtherPanelDelegate(txtNote_OnSetFocusToNextPanel);

            //  The user can move out of the editor through a keypress.
            this.txtNote.OnSetFocusToPreviousPanel += new NotesTextbox.SetFocusToOtherPanelDelegate(txtNote_OnSetFocusToPreviousPanel);

            //  Find the last used savefile.
            //TODO:Move this functionality to the Kopainsettings or Setting class and just call it from here.
            if (null == filename)
            {
                filename = KopainSetting.Instance.Settings.GetLastUsedMRUFile();  //  After this the filename is still null if there was no last MRU file.
            }

            LoadAndShowSavefile(filename);

            //  Show the form as MDI or SDI.
            //
            if (null == this.MdiParent)
            {
                //  SDI Application.
            }
            else
            {
                //  MDI Application.

                //  We have to set the file menu to invisible explicit because otherwise it will pop up in the MDI.
                fileToolStripMenuItem.Visible = false;
            }
        }
        
        /// <summary>This method updates the statuslist.
        /// It takes a bunch of parameters and this method then finds out what to update.
        /// </summary>
        /// <param name="note"></param>
        private void UpdateStatuslist(NoteType note)
        {
            statusStripMain.SetPath(note.Root.path);
            statusStripMain.SetFilename(note.file);
        }

#region MRU methods.

        /// <summary>This method adds a Savefile to the MRU list in the Settings file.  If the Savefile already exists it is positioned at the top of the list.
        /// </summary>
        /// <param name="filename"></param>
        private void AddMRUFile(string filename)
        {
            KopainSetting.Instance.Settings.AddMRUFile(filename);
        }


        /// <summary>This method deletes a Savefile from teh MRU list in the Settings file.
        /// </summary>
        /// <param name="filename"></param>
        private void DeleteMRUFile(string filename)
        {
            KopainSetting.Instance.Settings.DeleteMRUFile(filename);
        }

        /// <summary>This method populates the MRU list in the menu.
        /// This method is called when the user tries to show the MRU list.
        /// </summary>
        private void PopulateMRUList()
        {
            //  First clear the old contents.
            //  There could be a check so we don't clear and fill when not necessary, when the
            //  MRU list is the same.  But I don't want to implement that right now.
            //
            mnuRecentFiles.DropDown.Items.Clear();

            //  Then fill with the latest MRU.
            //
            for (int i = 0; i < KopainSetting.Instance.Settings.MRU.Length; i++)
            {
                FileType file = KopainSetting.Instance.Settings.MRU[i];
                ToolStripMenuItem mnu = new ToolStripMenuItem(file.Name);
                mnu.Click += new EventHandler(mnuMRUItem_Click);
                mnuRecentFiles.DropDown.Items.Add(mnu);
            }
        }

#endregion   // MRU methods.


#endregion  //  Form metods.

#region File methods.
        
        /// <summary>This method creates a new file and loads it.
        /// </summary>
        private void CreateNewFile()
        {
            using( SaveFileDialog dlg = new SaveFileDialog() ){
                dlg.AddExtension = true;
                dlg.OverwritePrompt = true;
                dlg.SupportMultiDottedExtensions = true;
                dlg.DefaultExt = Constant.DefaultFullExtension;
                dlg.ValidateNames = true;
                dlg.AutoUpgradeEnabled = true;
                dlg.Filter = "Kopain files(*." + dlg.DefaultExt + ")|*." + dlg.DefaultExt + "|All files|*.*";
                if (DialogResult.OK == dlg.ShowDialog(this))
                {

                    if( null != _saveFile )
                    {
                        SaveSavefile();
                    }

                    //  The user said ok to create a new file.  Copy the template.
                    //
                    File.Copy( Constant.KopainPath + @"\" + KopainSetting.Instance.Settings.NewFileTemplate, dlg.FileName, true );

                    //  Load the file.
                    //
                    LoadAndShowSavefile( dlg.FileName );
                }
            }
        }

        /// <summary>This method asks the user for a Savefile to open and opens it.
        /// </summary>
        private void OpenExistingFile()
        {
            using( OpenFileDialog dlg = new OpenFileDialog() )
            {
                dlg.AddExtension = true;
                dlg.CheckFileExists = true;
                dlg.CheckPathExists = true;
                dlg.Multiselect = false;
                dlg.DefaultExt = Constant.DefaultFullExtension;
                dlg.SupportMultiDottedExtensions = true;
                dlg.ValidateNames = true;
                dlg.AutoUpgradeEnabled = true;
                dlg.Filter = "Kopain files(*." + dlg.DefaultExt + ")|*." + dlg.DefaultExt + "|All files|*.*";
                if( DialogResult.OK == dlg.ShowDialog( this ) )
                {

                    if( null != tvNotes.SelectedNode )
                    {
                        SaveNote( tvNotes.GetSelectedNote() );
                    }
                    if( null != _saveFile )
                    {
                        SaveSavefile();
                    }

                    //  The user said ok to open a file.
                    //
                    LoadAndShowSavefile( dlg.FileName );
                    //AddMRUFile( dlg.FileName );
                    KopainSetting.Instance.Save();
                }
            }
        }

        /// <summary>This method loads a Savefile and shows it.
        /// It is up to the caller to save the old file.
        /// </summary>
        /// <param name="filename"></param>
        private bool LoadAndShowSavefile( string filename )
        {
            //  Open the savefile.
            //
            if( null != filename )
            {
                try
                {
                    _saveFile = new Savefile( filename );
                }
                catch( Exception.CorruptSaveFile )
                {
                    MessageBox.Show(this,
                        string.Format( "The Savefile [{0}] is corrupt.  The file cannot be opened.", filename ), "Kopain - Corrupt Savefile",
                        MessageBoxButtons.OK, MessageBoxIcon.Exclamation );
                    tvNotes.Enabled = false; //  How come this doesn't grey out the treeview?
                    txtNote.Enabled = false;
                }
                catch( Exception.FileWasNotFoundException exc )
                {
                    MessageBox.Show(this,
                        string.Format( "The {0} was not found.", exc.Filename ), "Kopain - Savefile missing",
                        MessageBoxButtons.OK, MessageBoxIcon.Exclamation );
                    tvNotes.Enabled = false; //  How come this doesn't grey out the treeview?
                    txtNote.Enabled = false;
                }
                catch( Exception.DirectoryWasNotFoundException exc )
                {
                    MessageBox.Show(this,
                        string.Format( "Part of the path {0} was not found.", exc.Path ), "Kopain - Savefile missing",
                        MessageBoxButtons.OK, MessageBoxIcon.Exclamation );
                    tvNotes.Enabled = false; //  How come this doesn't grey out the treeview?
                    txtNote.Enabled = false;
                }
            }

            //  Only continue with showing the Savefile if we tried and succeeded in loading the Savefile.
            //
            if (null == _saveFile && null != filename)
            {
                if ( KopainSetting.Instance.Settings.HasMRUFile(filename))
                {
                    if (DialogResult.Yes == MessageBox.Show(this, "There was no file [" + filename + "].\n\nShould it be removed from the MRU (Most Recently Used) list?", "Load", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button1))
                    {
                        DeleteMRUFile(filename);
                        KopainSetting.Instance.Save();
                    }
                }
                return false;
            }

            if (null == _saveFile)
            {
                //  We have not Savefile so disable the tree and the edit form.
                tvNotes.Enabled = false;
                txtNote.Enabled = false;
            }
            else
            {
                //  Close the file shown from before.
                //  It is up to the caller to save it beforehand.
                //
                tvNotes.ClearTree();

                //  Show the newly opened savefile.
                tvNotes.ConstructTree(_saveFile.NoteRoot.Note);

                tvNotes.Enabled = true;
                txtNote.Enabled = true;
            }

            //  Set the title bar.
            //
            TitleBar.Instance.Filename = filename ?? "";
            this.Text = TitleBar.Instance.ToString();

            //  Update the settings.
            //
            if( null != filename )
            {
                AddMRUFile( filename );
                KopainSetting.Instance.Save();
            }

            //  Select the last selected Note if there is any.
            //
            if (string.Empty == _saveFile.NoteRoot.openNoteId)
            {   // There was no earlier selected Note.
                if (tvNotes.Nodes.Count >= 1)
                {
                    tvNotes.SelectedNode = tvNotes.Nodes[0];
                }
            }
            else
            {   // Select the Note that was selected at last closing.  If there is still such a Note.
                TreeNode node = tvNotes.GetNodeById(_saveFile.NoteRoot.openNoteId);
                if (null == node)
                {
                    if (tvNotes.Nodes.Count >= 1)
                    {
                        tvNotes.SelectedNode = tvNotes.Nodes[0];
                    }
                }
                else
                {
                    tvNotes.SelectedNode = node;
                }
            }

            return true;
        }

        /// <summary>This method returns the contents of a text file.
        /// </summary>
        /// <param name="filename"></param>
        /// <returns></returns>
        private static string GetContentsOfFile( string filename )
        {
            string ret = "";
            try
            {
                using( StreamReader sr = new StreamReader( filename ) )
                {
                    ret += sr.ReadToEnd();
                }
            }
            catch( FileNotFoundException exc )
            {
                throw new Exception.FileWasNotFoundException( filename, exc );
            }
            return ret;
        }

        /// <summary>This method saves a string to a text file.
        /// Please note that is is a subfile, not the File.
        /// </summary>
        /// <param name="filename"></param>
        /// <param name="text"></param>
        private static void SaveSubFile( string filename, string text )
        {
            using( StreamWriter writer = new StreamWriter( filename ) )
            {
                writer.Write( text );
            }

        }

        /// <summary>This method saves the File(=the Savefile);
        /// </summary>
        private void SaveSavefile()
        {
            System.Diagnostics.Debug.WriteLine("SaveSavefile", "enter"); System.Diagnostics.Debug.Indent();
            //  Check that the Notes are correct.
            //  Just a help for debugging...
            //
            //  Loop through all notes and check that either 'file' or 'Data' has data.  Only one of them can.  This should be implemented in the xsd.
            List<NoteType> allNotesList =_saveFile.NoteRoot.GetAllNotesDepthFirst();
            foreach( NoteType note in allNotesList ){
                if( ( note.file != string.Empty ) && ( note.Data != string.Empty ) ){
                    throw new Exception.CorruptSaveFile( note );
                }
            }

            //  Serialize the notes and save to the Savefile.
            //
            _saveFile.Save();
            ////TODO:Move the serialization part to the Note.partial.cs file.
            //XmlSerializer serz = new XmlSerializer( typeof( NoteRoot ) );
            //using( StreamWriter writer = new StreamWriter( _saveFile.FilenameWithPath ) )
            //{
            //    serz.Serialize( writer, _saveFile.NoteRoot );
            //    writer.Close();
            //}

            //  Save a backup.
            //
            //  Check if the user wants to do an automatic backup, this is set in the settings file.
            //
            string backupTemplate = KopainSetting.Instance.Settings.BackupTemplate;
            if( "" != backupTemplate )
            {
                //  Erase every backup except the X that we want to keep.
                //
                string backupFilename = Backup.EraseOld( _saveFile.FilenameWithPath );
                //  Save the new Savefile by copying the freshly saved.
                //
                System.IO.File.Copy( _saveFile.FilenameWithPath, backupFilename, true );
            }
            System.Diagnostics.Debug.Unindent(); System.Diagnostics.Debug.WriteLine("SaveSavefile", "leave");
        }

#endregion  //  File methods.

#region Note methods.

        /// <summary>This method saves the contents for the Note.
        /// </summary>
        /// <param name="note"></param>
        private void SaveNote( NoteType note )
        {
            System.Diagnostics.Debug.WriteLine("FormMain.SaveNote", "Enter"); System.Diagnostics.Debug.Indent();

            if (string.Empty == note.file)
            {
                note.Data = txtNote.Rtf;
            }
            else
            {
                //  Save the file.
                SaveSubFile( note.FileWithPath( _saveFile.NoteRoot ), txtNote.Rtf );
            }

            note.cursorPosition = txtNote.SelectionStart;
            SaveSavefile();

            System.Diagnostics.Debug.Unindent(); System.Diagnostics.Debug.WriteLine("FormMain.SaveNote", "Leave");
        }

        ///// <summary>This method saves the cursor position.  Call this method _before_ the editor is loaded with a new node.
        ///// </summary>
        ///// <param name="note"></param>
        //private void SaveCursorPosition(NoteType note)
        //{
        //    System.Diagnostics.Debug.WriteLine("FormMain.SaveCursorPosition", "Enter"); System.Diagnostics.Debug.Indent();


        //    System.Diagnostics.Debug.Unindent(); System.Diagnostics.Debug.WriteLine("FormMain.SaveCursorPosition", "Leave");
        //}

        /// <summary>This method shows a dialogue about a Note.
        /// </summary>
        private void ShowNoteInfo()
        {
            NoteType activeNote = tvNotes.GetSelectedNote();
            using (FormShowNoteInfo form = new FormShowNoteInfo(activeNote, _saveFile.NoteRoot))
            {
                if (DialogResult.OK == form.ShowDialog(this))
                {
                    SaveSavefile();
                }
                if (FormShowNoteInfo.ChangesType.Title == (form.Changes & FormShowNoteInfo.ChangesType.Title))
                {
                    tvNotes.UpdateSelectedNodeTitle();
                }
            }
            UpdateStatuslist(activeNote);
        }

#endregion  //  Note methods.

#region Node methods.
        
        /// <summary>This method changes Note.
        /// </summary>
        /// <param name="navigateType"></param>
        private void SelectRelativeNode( NotesTextbox.NavigateTypes navigateType )
        {
            switch( navigateType )
            {
                case NotesTextbox.NavigateTypes.Up:
                    tvNotes.SelectedNode = tvNotes.GetPreviousVisibleNode();
                    break;
                case NotesTextbox.NavigateTypes.Down:
                    tvNotes.SelectedNode = tvNotes.GetNextVisibleNode();
                    break;
                case NotesTextbox.NavigateTypes.Left:
                    break;
                case NotesTextbox.NavigateTypes.Right:
                    break;
            }
        }

        /// <summary>This method adds a child note to the active Note.
        /// </summary>
        private void TreeNodeAddChild()
        {
            TreeNode newNode = tvNotes.AddChildToActiveNode( _saveFile.NoteRoot );
            SaveSavefile();
            tvNotes.SelectedNode = newNode;
        }

        /// <summary>This method adds a sibling note to the active Note.
        /// </summary>
        private void TreeNodeAddSibling()
        {
            TreeNode newNode = tvNotes.AddSiblingToActiveNode( _saveFile.NoteRoot );
            SaveSavefile();
            tvNotes.SelectedNode = newNode;
        }

        /// <summary>This method sets the treeview into a name changing mode.
        /// </summary>
        private void TreeNodeChangeName()
        {
            tvNotes.SetModeToChangeName();
        }

        /// <summary>This method deletes the active note.
        /// </summary>
        private void TreeNodeDelete()
        {
            tvNotes.DeleteActiveNode( _saveFile.NoteRoot );
            SaveSavefile();
        }

        /// <summary>This method moves the selected Node upwards, to a lower index.
        /// </summary>
        private void TreeNodeMoveUp()
        {
            tvNotes.MoveActiveNode( NotesTreeview.MoveDirection.Up );
        }

        /// <summary>This method moves the selected Node downwards, to a higher index.
        /// </summary>
        private void TreeNodeMoveDown()
        {
            tvNotes.MoveActiveNode( NotesTreeview.MoveDirection.Down );
        }

        /// <summary>This method moves the selected Node leftwards, up in the hierarchy.
        /// </summary>
        private void TreeNodeMoveLeft()
        {
            tvNotes.MoveActiveNode( NotesTreeview.MoveDirection.Left );
        }

        /// <summary>This method moves the selected Node rightwards, down in the hierarchy.
        /// </summary>
        private void TreeNodeMoveRight()
        {
            tvNotes.MoveActiveNode( NotesTreeview.MoveDirection.Right );
        }

#endregion  //  Node methods.

#region Export methods.

        /// <summary>This method exports the whole tree to a file/directory-structure.
        /// The user is asked for target location.
        /// </summary>
        private void ExportSavefile()
        {
            //  Save the visible note.
            SaveNote(tvNotes.GetSelectedNote());

            //  Open a dialogue to ask the user where to put the result.
            //  Then export.
            using (SaveFileDialog dlg = new SaveFileDialog())
            {
                dlg.AddExtension = true;
                dlg.CheckPathExists = true;
                dlg.DefaultExt = "";
                dlg.FileName = System.IO.Path.GetFileNameWithoutExtension(_saveFile.FilenameWithPath);
                dlg.OverwritePrompt = true;
                dlg.SupportMultiDottedExtensions = true;
                if (DialogResult.OK == dlg.ShowDialog(this))
                {

                    //  Export.
                    Export.ExportSavefile(
                        System.IO.Path.GetDirectoryName(dlg.FileName),
                        System.IO.Path.GetFileName(dlg.FileName),
                        _saveFile.NoteRoot.Note);
                }
            }
        }

#endregion  //  Export methods.

#endregion  //  Presentation methods.

    }
}